package com.levi.queue;

import java.util.Scanner;

/**
 * @author shentong
 * @date 2021/8/22 20:41
 * @Description 数组实现环形队列
 */
public class CircleArrayQueue {
    public static void main(String[] args) {
        CircleQueueByArray queue = new CircleQueueByArray(4);
        Scanner scanner = new Scanner(System.in);
        boolean flag = true;
        while (flag){
            System.out.println("a (往队列添加数据)");
            System.out.println("g (取数据)");
            System.out.println("h (查看队列头部的数据)");
            System.out.println("e (退出程序)");
            System.out.println("s (显示队列中的数据)");
            char c = scanner.next().charAt(0);
            switch (c){
                case 'a':
                    System.out.println("请输入要加入的数据:");
                    int i = scanner.nextInt();
                    try {
                        queue.add(i);
                    } catch (Exception e) {
                        System.out.println(e.getMessage());
                    }
                    break;
                case 'g':
                    try {
                        System.out.println("取出的数据是:"+queue.get());
                    } catch (Exception e) {
                        System.out.println(e.getMessage());
                    }
                    break;
                case 's':
                    try {
                        queue.list();
                    } catch (Exception e) {
                        System.out.println(e.getMessage());
                    }
                    break;
                case 'h':
                    try {
                        System.out.println("头部数据是:"+queue.head());
                    } catch (Exception e) {
                        System.out.println(e.getMessage());
                    }
                    break;
                case 'e':
                    flag = false;
                    scanner.close();
                    System.out.println("退出程序------");
                    break;
                default:
                    break;
            }
        }
        System.out.println("程序退出----");
    }
}
class CircleQueueByArray{
    private int front;
    private int real;
    private int maxSize;
    private int[] arr;

    public CircleQueueByArray(int maxSize) {
        this.maxSize = maxSize;
        this.front = 0; //指向队列的第一个数据的位置
        this.real = 0; //指向最后一个位置的后一个位置  队列会空出来一个约定位置，这个位置是动态变化的，所以队列可以放的最大个数为maxSize-1
        this.arr = new int[maxSize];
    }

    /**
     * 判断队列是否已满
     */
    public boolean isFull() {
        return (real + 1) % maxSize == front;
    }

    /**
     * 判断队列是否为空
     */
    public boolean isEmpty() {
        return real == front;
    }

    /**
     * 往队列里面加数据
     * @param a
     */
    public void add(int a) {
        //判断队列是否已满
        if (isFull()) {
            throw new RuntimeException("队列已满，无法添加数据");
        }
        //往队列里面添加数据
        arr[real] = a;
        real = (real + 1) % maxSize;
    }

    /**
     * 取数据
     */
    public int get() {
        //判断队列是否为空
        if (isEmpty()) {
            throw new RuntimeException("队列为空，不能取数据");
        }
        int i = arr[front];
        front = (front + 1) % maxSize;
        return i;
    }

    /**
     * 查看队列的头部位置
     */
    public int head() {
        if (isEmpty()) {
            throw new RuntimeException("队列为空");
        }
        //front定义的就是队列的头部位置
        return arr[front];
    }

    /**
     * 遍历队列里面的数据
     */
    public void list() {
        //队列一直是连续的，第一个元素的下标是front,所以要从front开始遍历
        for (int i = front; i < front+size(); i++) {
            //i可能比maxSize大，所以要取模
            System.out.printf("arr[%d]=%d\t",(i+maxSize) % maxSize,arr[(i+maxSize) % maxSize]);
        }
        System.out.println();
    }

    /**
     * 获取队列中有效元素的个数
     * @return
     */
    public int size() {
        return (real + maxSize - front) % maxSize;
    }
}
